#include "VerifyCodeWidget.h"
#include <QPainter>
#include <QFont>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QDateTime>

VerifyCodeWidget::VerifyCodeWidget(QWidget* parent)
    : QWidget(parent),
    randomGenerator(QDateTime::currentMSecsSinceEpoch())
{
    this->setFixedSize(100, 40);
    refreshVerifyCode();
}

void VerifyCodeWidget::refreshVerifyCode()
{
    generateVerifyCode();                  // 生成文本
    cachedPixmap = generateVerifyPixmap(); // 生成图像
    this->update();                        // 更新界面
}

QString VerifyCodeWidget::getVerifyCode() const
{
    return verifyCode;
}

void VerifyCodeWidget::generateVerifyCode()
{
    verifyCode.clear();
    for (int i = 0; i < 4; ++i) {
        QChar ch('A' + randomGenerator.bounded(26));
        verifyCode.append(ch);
    }
}

QPixmap VerifyCodeWidget::generateVerifyPixmap()
{
    QPixmap pix(size());
    pix.fill(Qt::white);

    QPainter painter(&pix);
    painter.setRenderHint(QPainter::Antialiasing);

    // 干扰线
    for (int i = 0; i < 20; ++i) {
        painter.setPen(QPen(QColor(randomGenerator.bounded(256), randomGenerator.bounded(256), randomGenerator.bounded(256))));
        painter.drawLine(randomGenerator.bounded(width()), randomGenerator.bounded(height()),
                         randomGenerator.bounded(width()), randomGenerator.bounded(height()));
    }

    // 噪点
    for (int i = 0; i < 300; ++i) {
        painter.setPen(QColor(randomGenerator.bounded(256), randomGenerator.bounded(256), randomGenerator.bounded(256)));
        painter.drawPoint(randomGenerator.bounded(width()), randomGenerator.bounded(height()));
    }

    // 验证码字母
    QFont font("Arial", height() / 2, QFont::Bold, true);
    painter.setFont(font);

    for (int i = 0; i < verifyCode.size(); ++i) {
        painter.setPen(QColor(randomGenerator.bounded(256),  randomGenerator.bounded(256), randomGenerator.bounded(256)));
        painter.drawText(5 + 20 * i, randomGenerator.bounded(10), 30, 30, Qt::AlignCenter, QString(verifyCode[i]));
    }

    return pix;
}

void VerifyCodeWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    if (!cachedPixmap.isNull()) {
        painter.drawPixmap(0, 0, cachedPixmap);
    }
}

void VerifyCodeWidget::mousePressEvent(QMouseEvent* event)
{
    Q_UNUSED(event);
    refreshVerifyCode();
}

bool VerifyCodeWidget::checkVerifyCode(const QString& input) const
{
    // 忽略大小写
    return input.compare(verifyCode, Qt::CaseInsensitive) == 0;
}
